// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: daniel

#pragma once

#include <memory>
#include <set>
#include <string>
#include <utility>

#include "coin/proto/coin_order_enums.pb.h"
#include "coin2/exchange/base/api_base/asio_http_context.h"
#include "coin2/exchange/base/order/parser.h"

namespace coin2::exchange::coinone::order_v2 {

class CoinoneParser : public base::order::BaseParser {
  using JsonValue = base::order::BaseParser::JsonValue;
  using SubmitOrderResponse = base::order::BaseParser::SubmitOrderResponse;
  using ProductOrderBundle = base::order::BaseParser::ProductOrderBundle;
  using ProductFillBundle = base::order::BaseParser::ProductFillBundle;
  using AccountBalance = base::order::BaseParser::AccountBalance;
  using ProductOrderElement = base::order::BaseParser::ProductOrderElement;
  using ProductFillElement = base::order::BaseParser::ProductFillElement;
  using AccountPosition = base::order::BaseParser::AccountPosition;
  using OrderErrorCode = base::order::BaseParser::OrderErrorCode;
  using OrderSubTopicId = base::order::BaseParser::OrderSubTopicId;
  using OrderSide = coin::proto::OrderSide;
  using OrderType = coin::proto::OrderType;
  using CurrencyPairs = std::set<std::pair<std::string, std::string>>;

 public:
  const ParseResult& ParseRawMessage(const RawMessage& msg) override;
  AccountBalance ParseBalance(const JsonValue& data) override;

 private:
  void ParseSubmitResponse();
  void ParseCancelResponse();
  void ParseRestOrdersInfo();
  void ParseRestFillInfoList();
  void ParseRestAccountBalance();
  void ParseWsMessage();

  void ParseRestLimitOrder(const JsonValue& data, ProductOrderElement* product_order_element);
  void ParseRestFillInfo(const JsonValue& data, ProductFillElement* product_fill_element);
  void ParseRestOrderInfo(const JsonValue& data, ProductOrderElement* product_order_element);

  int64_t GetTimestamp(const std::string& time_str) const;
  int GetErrorCode(const JsonValue& data) const;
  std::string GetErrorMsg(const JsonValue& data) const;
  bool IsCoinoneErrMessage(const JsonValue& data) const;
  int64_t GetProcOrderId(const JsonValue& data) const;
  OrderSide GetOrderSide(const std::string& side) const;
  OrderType GetOrderType(const std::string& type) const;
  const CurrencyPairs& native_currencies() const;

 private:
  std::string current_native_symbol_;
};

}  // namespace coin2::exchange::coinone::order_v2
